package org.eiahe.hr.training.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.github.linpeilie.Converter;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import cn.dev33.satoken.stp.StpUtil;
import org.ehe.common.core.constant.RoleKeyConstants;
import org.ehe.common.satoken.utils.LoginHelper;
import org.ehe.system.domain.HrEmployee;
import org.ehe.system.domain.vo.HrEmployeeVo;
import org.ehe.system.domain.vo.SysDeptVo;
import org.ehe.system.domain.vo.SysPostVo;
import org.ehe.system.domain.vo.SysUserVo;
import org.ehe.system.service.IHrEmployeeService;
import org.ehe.system.service.ISysDeptService;
import org.ehe.system.service.ISysPostService;
import org.ehe.system.service.ISysUserService;
import org.eiahe.hr.training.domain.vo.HrTrainingCourseStudentVo;
import org.eiahe.hr.training.domain.vo.HrTrainingMaterialVo;
import org.eiahe.hr.training.domain.HrTrainingCourse;
import org.eiahe.hr.training.domain.HrTrainingCourseMaterial;
import org.eiahe.hr.training.domain.HrTrainingCourseStudent;
import org.eiahe.hr.training.domain.bo.HrTrainingCourseBo;
import org.eiahe.hr.training.domain.bo.HrTrainingRecordBo;
import org.eiahe.hr.training.domain.vo.HrTrainingCourseVo;
import org.eiahe.hr.training.mapper.HrTrainingCourseMaterialMapper;
import org.eiahe.hr.training.mapper.HrTrainingCourseMapper;
import org.eiahe.hr.training.mapper.HrTrainingCourseStudentMapper;
import org.eiahe.hr.training.mapper.HrTrainingMaterialMapper;
import org.eiahe.hr.training.service.IHrTrainingCourseService;
import org.ehe.common.mybatis.core.page.PageQuery;
import org.ehe.common.mybatis.core.page.TableDataInfo;
import org.eiahe.hr.training.service.IHrTrainingRecordService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 培训课程Service业务层处理
 *
 * @author zhangnn
 */
@RequiredArgsConstructor
@Service
public class HrTrainingCourseServiceImpl implements IHrTrainingCourseService {

    private final HrTrainingCourseMapper baseMapper;
    private final HrTrainingCourseMaterialMapper courseMaterialMapper;
    private final HrTrainingCourseStudentMapper courseStudentMapper;
    private final HrTrainingMaterialMapper materialMapper;
    private final IHrEmployeeService employeeService;
    private final Converter converter;
    private final IHrTrainingRecordService trainingRecordService;
    private final ISysUserService userService;
    private final ISysDeptService deptService;
    private final ISysPostService postService;

    /**
     * 查询培训课程
     */
    @Override
    public HrTrainingCourseVo queryById(Long courseId) {
        return baseMapper.selectVoById(courseId);
    }

    /**
     * 查询培训课程列表
     */
    @Override
    public TableDataInfo<HrTrainingCourseVo> queryPageList(HrTrainingCourseBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<HrTrainingCourse> lqw = buildQueryWrapper(bo);

        // 如果是HR相关角色则可以看到所有课程，否则只能看到分配给自己的课程
        if (!(StpUtil.hasRoleOr(RoleKeyConstants.getHrRoles().toArray(new String[0])))) {
            // 获取当前用户ID
            Long userId = LoginHelper.getUserId();
            // 查询分配给当前用户的课程ID列表
            List<HrTrainingCourseStudent> courseStudents = courseStudentMapper.selectList(
                    Wrappers.lambdaQuery(HrTrainingCourseStudent.class)
                            .eq(HrTrainingCourseStudent::getUserId, userId));

            if (CollUtil.isNotEmpty(courseStudents)) {
                List<Long> courseIds = courseStudents.stream()
                        .map(HrTrainingCourseStudent::getCourseId)
                        .distinct()
                        .collect(Collectors.toList());
                // 添加课程ID过滤条件
                lqw.in(HrTrainingCourse::getCourseId, courseIds);
            } else {
                // 如果没有分配的课程，添加一个永远不成立的条件，确保查询结果为空
                lqw.eq(HrTrainingCourse::getCourseId, -1L);
            }
        }

        Page<HrTrainingCourseVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        result.getRecords().forEach(h->{
            //判断当前登录用户是否学习完成
            Boolean isTraining = trainingRecordService.completeCourseByCourseIdAndEmpId(h.getCourseId(),LoginHelper.getUserId());
            if(isTraining){
                h.setTrainingStatus("1");
            }
            Date pureNow = DateUtil.beginOfDay(new Date());
            // 状态判断
            if (DateUtil.compare(h.getEndDate(), pureNow) < 0) {
                h.setStatus("2"); // 已结束
            } else if (DateUtil.compare(h.getStartDate(), pureNow) <= 0) {
                h.setStatus("1"); // 进行中
            }
        });
        return TableDataInfo.build(result);
    }

    /**
     * 查询培训课程列表
     */
    @Override
    public List<HrTrainingCourseVo> queryList(HrTrainingCourseBo bo) {
        LambdaQueryWrapper<HrTrainingCourse> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<HrTrainingCourse> buildQueryWrapper(HrTrainingCourseBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<HrTrainingCourse> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getCourseCode()), HrTrainingCourse::getCourseCode, bo.getCourseCode());
        lqw.like(StringUtils.isNotBlank(bo.getCourseName()), HrTrainingCourse::getCourseName, bo.getCourseName());
        lqw.eq(StringUtils.isNotBlank(bo.getCourseCategory()), HrTrainingCourse::getCourseCategory,
                bo.getCourseCategory());
        lqw.eq(StringUtils.isNotBlank(bo.getCourseType()), HrTrainingCourse::getCourseType, bo.getCourseType());
        lqw.eq(StringUtils.isNotBlank(bo.getCourseLevel()), HrTrainingCourse::getCourseLevel, bo.getCourseLevel());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), HrTrainingCourse::getStatus, bo.getStatus());
        lqw.orderByAsc(HrTrainingCourse::getSortOrder);
        lqw.orderByDesc(HrTrainingCourse::getCreateTime);
        return lqw;
    }

    /**
     * 新增培训课程
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String insertByBo(HrTrainingCourseBo bo) {
        String msg = "培训课程新增成功";
        // 根据code判断是否存在
        Long l = this.baseMapper.selectCount(new LambdaQueryWrapper<HrTrainingCourse>()
                .eq(HrTrainingCourse::getCourseCode, bo.getCourseCode()));
        if (l > 0) {
            return msg = "[" + bo.getCourseCode() + "]课程编码已经存在，请重新输入！";
        }

        HrTrainingCourse add = converter.convert(bo, HrTrainingCourse.class);
        add.setEnrolledCount(0);
        add.setCompletedCount(0);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setCourseId(add.getCourseId());
            // 保存课程课件关联
            if (CollUtil.isNotEmpty(bo.getMaterialIds())) {
                addCourseMaterial(add.getCourseId(), bo.getMaterialIds());
            }
            // 保存课程学员关联
            if (CollUtil.isNotEmpty(bo.getStudentIds())) {
                addCourseStudent(add.getCourseId(), bo.getStudentIds());
            }
            // 部门中人员关联
            if (StringUtils.isNotBlank(bo.getDeptIds())) {
                List<Long> userIds = userService.selectUserByDeptIds(bo.getDeptIds());
                if (CollUtil.isNotEmpty(userIds)) {
                    addCourseStudent(add.getCourseId(), userIds);
                }
            }
        }
        if (!flag) {
            msg = "新增课程培训失败！";
        }
        return msg;
    }

    /**
     * 修改培训课程
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByBo(HrTrainingCourseBo bo) {
        HrTrainingCourse update = converter.convert(bo, HrTrainingCourse.class);
        boolean flag = baseMapper.updateById(update) > 0;
        if (flag) {
            // 更新课程课件关联
            if (bo.getMaterialIds() != null) {
                // 先删除原有关联
                courseMaterialMapper.delete(Wrappers.lambdaQuery(HrTrainingCourseMaterial.class)
                        .eq(HrTrainingCourseMaterial::getCourseId, bo.getCourseId()));
                // 再添加新关联
                if (CollUtil.isNotEmpty(bo.getMaterialIds())) {
                    addCourseMaterial(bo.getCourseId(), bo.getMaterialIds());
                }
            }
            if(bo.getStudentIds() != null){
                courseStudentMapper.delete(Wrappers.lambdaQuery(HrTrainingCourseStudent.class)
                    .eq(HrTrainingCourseStudent::getCourseId, bo.getCourseId()));

                //再重新添加
                addCourseStudent(bo.getCourseId(),bo.getStudentIds());
            }
        }
        return flag;
    }

    /**
     * 批量删除培训课程
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteByIds(Collection<Long> courseIds) {
        // 删除课程课件关联
        courseMaterialMapper.delete(Wrappers.lambdaQuery(HrTrainingCourseMaterial.class)
                .in(HrTrainingCourseMaterial::getCourseId, courseIds));
        // 删除课程学员关联
        courseStudentMapper.delete(Wrappers.lambdaQuery(HrTrainingCourseStudent.class)
                .in(HrTrainingCourseStudent::getCourseId, courseIds));
        // 删除课程
        return baseMapper.deleteByIds(courseIds) > 0;
    }

    /**
     * 为课程添加课件
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addCourseMaterial(Long courseId, List<Long> materialIds) {
        if (CollUtil.isEmpty(materialIds)) {
            return false;
        }
        List<HrTrainingCourseMaterial> list = new ArrayList<>();
        for (int i = 0; i < materialIds.size(); i++) {
            HrTrainingCourseMaterial courseMaterial = new HrTrainingCourseMaterial();
            courseMaterial.setCourseId(courseId);
            courseMaterial.setMaterialId(materialIds.get(i));
            courseMaterial.setSortOrder(i + 1);
            courseMaterial.setIsRequired("1");
            list.add(courseMaterial);
        }
        return courseMaterialMapper.insertBatch(list);
    }

    /**
     * 为课程添加学员
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addCourseStudent(Long courseId, List<Long> employeeIds) {
        if (CollUtil.isEmpty(employeeIds)) {
            return false;
        }
        // 这里需要查询员工信息,暂时简化处理
        List<HrTrainingCourseStudent> list = new ArrayList<>();
        for (Long eId : employeeIds) {
            HrTrainingCourseStudent student = new HrTrainingCourseStudent();
            HrEmployeeVo employee = employeeService.queryById(eId);
            if (Objects.nonNull(employee)) {
                student.setUserId(employee.getUserId());
                student.setCourseId(courseId);
                student.setEmployeeNo(employee.getEmployeeNo());
                student.setEmployeeId(employee.getEmployeeId());
                student.setEmployeeName(employee.getEmployeeName());
                student.setEnrollTime(new Date());
                student.setStudyProgress(0);
                student.setIsCompleted("0");
                student.setIsPassed("0");
                list.add(student);
            }
        }
        boolean flag = courseStudentMapper.insertBatch(list);
        if (flag) {
            // 更新课程报名人数
            HrTrainingCourse course = baseMapper.selectById(courseId);
            if (ObjectUtil.isNotNull(course)) {
                course.setEnrolledCount(course.getEnrolledCount() + employeeIds.size());
                baseMapper.updateById(course);
            }
        }
        return flag;
    }

    /**
     * 移除课程学员
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean removeCourseStudent(Long courseId, List<Long> employeeIds) {
        boolean flag = courseStudentMapper.delete(Wrappers.lambdaQuery(HrTrainingCourseStudent.class)
                .eq(HrTrainingCourseStudent::getCourseId, courseId)
                .in(HrTrainingCourseStudent::getEmployeeId, employeeIds)) > 0;
        if (flag) {
            // 更新课程报名人数
            HrTrainingCourse course = baseMapper.selectById(courseId);
            if (ObjectUtil.isNotNull(course)) {
                course.setEnrolledCount(Math.max(0, course.getEnrolledCount() - employeeIds.size()));
                baseMapper.updateById(course);
            }
        }
        return flag;
    }

    /**
     * 获取课程详情(含课件和学员)
     */
    @Override
    public HrTrainingCourseVo getCourseDetail(Long courseId) {
        HrTrainingCourseVo courseVo = baseMapper.selectVoById(courseId);
        if (ObjectUtil.isNull(courseVo)) {
            return null;
        }

        // 查询课程课件
        List<HrTrainingCourseMaterial> courseMaterials = courseMaterialMapper.selectList(
                Wrappers.lambdaQuery(HrTrainingCourseMaterial.class)
                        .eq(HrTrainingCourseMaterial::getCourseId, courseId)
                        .orderByAsc(HrTrainingCourseMaterial::getSortOrder));
        if (CollUtil.isNotEmpty(courseMaterials)) {
            List<Long> materialIds = courseMaterials.stream()
                    .map(HrTrainingCourseMaterial::getMaterialId)
                    .collect(Collectors.toList());
            List<HrTrainingMaterialVo> materials = materialMapper.selectVoByIds(materialIds);
            courseVo.setMaterialList(materials);
        }

        // 查询课程学员
        List<HrTrainingCourseStudentVo> hrTrainingCourseStudentVos = courseStudentMapper.selectVoList(
            new LambdaQueryWrapper<HrTrainingCourseStudent>()
                .eq(HrTrainingCourseStudent::getCourseId, courseId));
        hrTrainingCourseStudentVos.forEach(h->{
            SysUserVo sysUserVo = userService.selectUserById(Long.valueOf(h.getUserId()));
            if(Objects.nonNull(sysUserVo)){
                System.out.println(sysUserVo.getUserId());
                SysDeptVo sysDeptVo = deptService.selectDeptById(sysUserVo.getDeptId());
                h.setDeptName(sysDeptVo.getDeptName());
                List<SysPostVo> sysPostVos = postService.selectPostsByUserId(sysUserVo.getUserId());
                if(sysPostVos.size() > 0){
                    h.setDeptName(sysUserVo.getDeptName());
                    h.setPostName(sysPostVos.get(0).getPostName());
                }
            }
        });
        courseVo.setStudentList(hrTrainingCourseStudentVos);

        return courseVo;
    }

    /**
     * 开始学习
     *
     * @param courseId
     * @return
     */
    @Override
    public Boolean startCourseDetail(Long courseId) {
        Long userId = LoginHelper.getUserId();
        HrEmployee hrEmployee = employeeService.queryByUserId(userId);
        if (Objects.nonNull(hrEmployee)) {
            HrTrainingRecordBo record = new HrTrainingRecordBo();
            record.setUserId(userId);
            record.setEmployeeId(hrEmployee.getEmployeeId());
            record.setEmployeeName(hrEmployee.getEmployeeName());
            record.setEmployeeNo(hrEmployee.getEmployeeNo());
            record.setCourseId(courseId);
            HrTrainingCourseVo courseVo = this.baseMapper.selectVoById(courseId);
            record.setCourseName(courseVo.getCourseName());
            record.setTrainingType("1");
            record.setTrainingDate(new Date());
            record.setTrainingDuration(new BigDecimal(0));
            record.setTrainer(courseVo.getTrainer());
            record.setTrainingContent(courseVo.getCourseDesc());
            record.setStatus("0");
            record.setCreateBy(userId);
            record.setCreateTime(new Date());
            trainingRecordService.insertByBo(record);

            //更新
            HrTrainingCourseStudent student = courseStudentMapper.selectOne(new LambdaQueryWrapper<HrTrainingCourseStudent>()
                .eq(HrTrainingCourseStudent::getCourseId,courseId)
                .eq(HrTrainingCourseStudent::getUserId,userId)
            );
            student.setStartTime(new Date());
            courseStudentMapper.updateById(student);
        }
        return true;
    }
}
